from StlModel import StlModel
from layer import Layer
from GeomAlgo import intersectTriangleZPlane


class IntersectStl_match:
    def __init__(self, stlModel: StlModel, layerThk):
        self.stlModel = stlModel
        self.layerThk = layerThk
        self.layers = []
        self.intersect()

    def interect(self):
        pass

    def matchFacetZs_brutal(self, zs):
        for tri in self.stlModel.triangles:
            zMin, zMax = tri.zMinPnt(), tri.zMaxPnt()
            for z in zs:
                if z > zMax:
                    break
                if z >= zMin and z <= zMax:
                    tri.zs.append(z)

    def matchFacetZs_bisection(self, zs):
        n = len(zs)
        for tri in self.stlModel.triangles:
            zMin, zMax = tri.zMinPnt(), tri.zMaxPnt()
            low, up, mid = 0, n - 1, 0
            while up - low > 1:
                mid = int((up + low) / 2)
                if zs[mid] < zMin:
                    low = mid
                else:
                    up = mid
            start = up
            if zs[low] == zMin:
                start = low

            low, up = 0, n - 1
            while up - low > 1:
                mid = int((up + low) / 2)
                if zs[mid] < zMax:
                    low = mid
                else:
                    up = mid
            end = low
            if zs[up] == zMax:
                end = up
            tri.zs = zs[start : end + 1]

    def genLayerHeighs(self):
        xMin, xMax, yMin, yMax, zMin, zMax = self.stlModel.getBounds()
        zs, layerDic = [], {}
        z = zMin + self.layerThk
        while z < zMax:
            zs.append(z)
            layerDic[z] = Layer(z)
            z += self.layerThk
        return zs, layerDic

    def intersect(self):
        zs, layerDic = self.genLayerHeighs()
        self.matchFacetZs_bisection(zs)
        for triangle in self.stlModel.triangles:
            for z in triangle.zs:
                seg = intersectTriangleZPlane(triangle, z)
                if seg is not None:
                    layerDic[z].segments.append(seg)

        for layer in layerDic.values():
            self.layers.append(layer)
